package com.shou.config;

import com.sunlight.core.slEncryptor.utils.RSAUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.FileSystemResource;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 读取外部yml配置文件
 */
@Slf4j
public class ExternalConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        // 从环境变量中获取额外配置文件所在的目录
        String externalBasePath = environment.getProperty("CONFIG_DIR", System.getenv("CONFIG_DIR"));
        // 需要更改为本项目的配置文件名
        List<String> fileList = List.of("/application-car.yml");
        for (String fileName : fileList) {
            String externalConfigPath = externalBasePath + fileName;
            FileSystemResource resource = new FileSystemResource(externalConfigPath);
            try {
                log.info("Attempting to load external configuration from: " + externalConfigPath);
                if (resource.exists()) {
                    YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
                    List<PropertySource<?>> yamlProperties = loader.load("externalConfig", resource);
                    for (PropertySource<?> propertySource : yamlProperties) {
                        PropertySource<?> decryptExternalConfig = new MapPropertySource("externalConfig", decryptExternalConfig(propertySource));
                        environment.getPropertySources().addFirst(decryptExternalConfig);
                    }
                    log.info("Loaded external configuration from " + externalConfigPath);
                } else {
                    log.error("External configuration file not found: " + externalConfigPath);
                }
            } catch (IOException e) {
                log.error("Failed to load external configuration file", e);
            }
        }
    }

    /**
     * 将yml文件中的加密信息进行解密
     */
    private Map<String, Object> decryptExternalConfig(PropertySource<?> propertySource) {
        HashMap<String, Object> source = new HashMap<>();
        Map map = (Map) propertySource.getSource();
        // 复制配置
        map.keySet().forEach(key -> source.put(key.toString(), propertySource.getProperty(key.toString())));
        Object sunlightEncryptionKeys = source.get("sunlight.encryption-keys");
        // 没有配置sunlight.encryption-keys，不需要解密
        if (Objects.isNull(sunlightEncryptionKeys)) {
            return source;
        }
        // 对需要进行解密的字段进行处理
        String[] encryptionKeys = sunlightEncryptionKeys.toString().split(",");
        if (ArrayUtils.isNotEmpty(encryptionKeys)) {
            for (String key : encryptionKeys) {
                // 解密
                Object value = source.get(key);
                if (Objects.isNull(value)) {
                    throw new RuntimeException("请检查yml中sunlight.encryption-keys的值是否正确: " + key);
                }
                source.put(key, RSAUtil.decrypt(value.toString().trim(), RSAUtil.getPriKey()));
            }
        }
        return source;
    }
}
